﻿using System;
using System.Collections;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using RaGE.Properties;

namespace RaGE
{
    public partial class MainWindow
    {
        private void PWGShopMenu(bool state)
        {
            switch (state)
            {
                case true:
                    OpenMenuItem.Visible = false;
                    SaveMenuItem.Visible = false;
                    toolStripSeparator1.Visible = false;

                    MenuItem_PWGShopEdit.Visible = true;
                    PWLoadDB.Visible = true;
                    PWSaveDB.Visible = true;
                    toolStripSeparator2.Visible = true;

                    PWExport136.Visible = true;
                    PWExport144C.Visible = true;
                    PWExport144S.Visible = true;
                    toolStripSeparator3.Visible = true;

                    PWImport136.Visible = true;
                    PWImport144C.Visible = true;
                    PWImport144S.Visible = true;
                    toolStripSeparator4.Visible = true;
                    break;

                case false:
                    OpenMenuItem.Visible = true;
                    SaveMenuItem.Visible = true;
                    toolStripSeparator1.Visible = true;

                    MenuItem_PWGShopEdit.Visible = false;
                    PWLoadDB.Visible = false;
                    PWSaveDB.Visible = false;
                    toolStripSeparator2.Visible = false;

                    PWExport136.Visible = false;
                    PWExport144C.Visible = false;
                    PWExport144S.Visible = false;
                    toolStripSeparator3.Visible = false;

                    PWImport136.Visible = false;
                    PWImport144C.Visible = false;
                    PWImport144S.Visible = false;
                    toolStripSeparator4.Visible = false;
                    break;
            }
        }

        private static string PWTimestampToString(uint timestamp)
        {
            var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            origin = origin.AddSeconds(timestamp);
            return origin.ToString("yyyy-MM-dd HH:mm:ss");
        }

        private static uint PWStringToTimestamp(string date)
        {
            var target = DateTime.Parse(date); // parsing depends on culture, application was set to invariant culture
            return Convert.ToUInt32(target.Subtract( new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);
        }

        private void PWClickGetTimestamp(object sender, EventArgs e)
        {
            var currentTimestamp = (int) Convert.ToUInt32(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);

            if (GSHOP != null)
                GSHOP.timestamp = currentTimestamp;

            textBox_PWTimestamp.Text = PWTimestampToString((uint) currentTimestamp);
        }

        private static uint PWStringToSeconds(string time)
        {
            try
            {
                var times = time.Split(new[] { '-', ':' });
                return ((86400 * Convert.ToUInt32(times[0])) + (3600 * Convert.ToUInt32(times[1])) +
                    (60 * Convert.ToUInt32(times[2])) + Convert.ToUInt32(times[3]));
            }
            catch
            {
                return 0;
            }
        }

        private void PWGShopInitialize()
        {
            comboBox_PWdbSource.SelectedIndex = 0;
            comboBox_PWSaleOption.SelectedIndex = 0;
            comboBox_PWStatus.SelectedIndex = 0;
            comboBox_PWType.SelectedIndex = 0;
            comboBox_PWSurface.Items.Clear();

            PWClickGetTimestamp(null, null);
            var files = Directory.GetFiles(Application.StartupPath + "\\surfaces\\百宝阁");

            foreach (var t in files)
                comboBox_PWSurface.Items.Add(t.Replace(Application.StartupPath + "\\", "").Replace(".jpg", ".dds"));

            itemDescriptions = new SortedList();

            if (!File.Exists(Application.StartupPath + "\\" + "item_ext_desc.txt")) return;

            var sr = new StreamReader(Application.StartupPath + "\\" + "item_ext_desc.txt", System.Text.Encoding.GetEncoding("Unicode"));
            string line;

            while (!string.IsNullOrEmpty((line = sr.ReadLine())))
            {
                if (line == "" || line.StartsWith("/") || line.StartsWith("#")) continue;

                var pair = line.Split(new[] { '"' });
                itemDescriptions.Add(pair[0].Trim(), pair[1]);
            }

            sr.Close();
        }

        private static string PWSecondsToString(uint time)
        {
            try
            {
                var days = time / 86400;
                time = time - (days * 86400);

                var hours = time / 3600;
                time = time - (hours * 3600);

                var minutes = time / 60;
                var seconds = time - (minutes * 60);

                return (days.ToString("D2") + "-" + hours.ToString("D2") + ":" + minutes.ToString("D2") + ":" + seconds.ToString("D2"));
            }
            catch
            {
                return "0";
            }
        }

        private static string PWBytesToString(byte[] value, string code)
        {
            var enc = Encoding.GetEncoding(code);
            return enc.GetString(value);
        }

        private static byte[] PWStringToBytes(string value, string code, int bytes)
        {
            var enc = Encoding.GetEncoding(code);
            var target = new byte[bytes];
            var source = enc.GetBytes(value);

            Array.Copy(source, target, target.Length > source.Length ? source.Length : target.Length);
            return target;
        }

        private void PWMoveSubCat(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWCats.SelectedIndex <= -1 || listBox_PWSubCats.SelectedIndex <= -1) return;

            var sourceCat = listBox_PWCats.SelectedIndex;
            var sourceSubCat = listBox_PWSubCats.SelectedIndex;
            var targetCat = toolStripMenuItem_PWMoveCat.DropDownItems.IndexOf((ToolStripMenuItem)sender);

            if (GSHOP.categories[targetCat].sub_cats.Length < 8)
            {
                var targetSubCat = GSHOP.categories[targetCat].sub_cats_count;

                // create new subCat in target cat
                GSHOP.categories[targetCat].sub_cats_count++;
                Array.Resize(ref GSHOP.categories[targetCat].sub_cats, GSHOP.categories[targetCat].sub_cats_count);
                GSHOP.categories[targetCat].sub_cats[GSHOP.categories[targetCat].sub_cats.Length - 1] = GSHOP.categories[sourceCat].sub_cats[sourceSubCat];

                // move all items to new subCat
                foreach (var t in GSHOP.items.Where(t => t.cat_index == sourceCat && t.sub_cat_index == sourceSubCat))
                {
                    t.cat_index = targetCat;
                    t.sub_cat_index = targetSubCat;
                }

                // delete source subCat
                PWSubCatDelClick(null, null);

                PWBuildContextMenus();
            }
            else
            {
                MessageBox.Show(Resources.Already8SubCats);
            }
        }

        private void PWBuildContextMenus()
        {
            toolStripMenuItem_PWMoveCat.DropDownItems.Clear();
            toolStripMenuItemPWMoveItem.DropDownItems.Clear();

            for (var i = 0; i < GSHOP.categories.Length; i++)
            {
                toolStripMenuItem_PWMoveCat.DropDownItems.Add(PWBytesToString(GSHOP.categories[i].name, "Unicode").Split(new[]{'\0'})[0]);
                toolStripMenuItem_PWMoveCat.DropDownItems[i].Click += PWMoveSubCat;
                toolStripMenuItemPWMoveItem.DropDownItems.Add(PWBytesToString(GSHOP.categories[i].name, "Unicode").Split(new[]{'\0'})[0]);

                for (var n = 0; n < GSHOP.categories[i].sub_cats.Length; n++)
                {
                    ((ToolStripMenuItem)toolStripMenuItemPWMoveItem.DropDownItems[i]).DropDownItems.Add(PWBytesToString(GSHOP.categories[i].sub_cats[n],
                        "Unicode").Split(new[]{'\0'})[0]);
                    ((ToolStripMenuItem)toolStripMenuItemPWMoveItem.DropDownItems[i]).DropDownItems[n].Click += PWMoveItem;
                }
            }
        }
        
        private void PWSubCatDelClick(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWCats.SelectedIndex <= -1 || listBox_PWSubCats.SelectedIndex <= -1) return;

            GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats_count--;

            var temp = new byte[GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats_count][];
            Array.Copy(GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats, 0, temp, 0, listBox_PWSubCats.SelectedIndex);
            Array.Copy(GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats, listBox_PWSubCats.SelectedIndex + 1, temp,
                listBox_PWSubCats.SelectedIndex, GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats_count - listBox_PWSubCats.SelectedIndex);
            GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats = temp;

            // remove items / update subcats of all items
            foreach (var t in GSHOP.items.Where(t => t.cat_index == listBox_PWCats.SelectedIndex))
            {
                if (t.sub_cat_index == listBox_PWSubCats.SelectedIndex)
                {
                    // mark this item as not to be saved
                    GSHOP.item_count--;
                    t.cat_index = -1;
                    t.sub_cat_index = -1;
                    item_id_index_map.Remove(t.shop_id);
                }

                if (t.sub_cat_index > listBox_PWSubCats.SelectedIndex)
                {
                    t.sub_cat_index--;
                }
            }

            listBox_PWSubCats.Items.RemoveAt(listBox_PWSubCats.SelectedIndex);
            listBox_PWItems.Items.Clear();
        }

        private void PWMoveItem(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWItems.SelectedIndex <= -1) return;

            var id = Convert.ToInt32(listBox_PWItems.SelectedItem.ToString().
                Substring(1, listBox_PWItems.SelectedItem.ToString().IndexOf("]", StringComparison.Ordinal) - 1));
            var currentItemIndex = (int)item_id_index_map[id];

            for (var i = 0; i < toolStripMenuItemPWMoveItem.DropDownItems.Count; i++)
            {
                if (!((ToolStripMenuItem)
                      toolStripMenuItemPWMoveItem.DropDownItems[i]).DropDownItems.Contains((ToolStripMenuItem) sender))
                    continue;

                GSHOP.items[currentItemIndex].cat_index = i;
                GSHOP.items[currentItemIndex].sub_cat_index =
                    ((ToolStripMenuItem)toolStripMenuItemPWMoveItem.DropDownItems[i]).DropDownItems.IndexOf((ToolStripMenuItem)sender);
                break;
            }

            listBox_PWItems.Items.RemoveAt(listBox_PWItems.SelectedIndex);
        }

        private void PWCatsIndexChanged(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWCats.SelectedIndex <= -1) return;

            if (listBox_PWCats.SelectedItem.ToString() != textBox_PWCat.Text)
                textBox_PWCat.Text = PWBytesToString(GSHOP.categories[listBox_PWCats.SelectedIndex].name, "Unicode");

            listBox_PWSubCats.Items.Clear();
            listBox_PWItems.Items.Clear();

            foreach (var t in GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats)
                listBox_PWSubCats.Items.Add(PWBytesToString(t, "Unicode"));
        }

        private void PWSubCatsIndexChanged(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWCats.SelectedIndex <= -1 || listBox_PWSubCats.SelectedIndex <= -1) return;

            if (listBox_PWSubCats.SelectedItem.ToString() != textBox_PWSubCat.Text)
                textBox_PWSubCat.Text =
                    PWBytesToString(GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats[listBox_PWSubCats.SelectedIndex], "Unicode");

            listBox_PWItems.Items.Clear();

            foreach (var t in GSHOP.items.Where(t => t.cat_index == listBox_PWCats.SelectedIndex &&
                t.sub_cat_index == listBox_PWSubCats.SelectedIndex))
                listBox_PWItems.Items.Add("[" + t.shop_id + "] " + PWBytesToString(t.name, "Unicode"));
        }

        private void PWChangeItem(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWItems.SelectedIndex <= -1) return;

            var id = Convert.ToInt32(listBox_PWItems.SelectedItem.ToString().Substring(1, listBox_PWItems.SelectedItem.ToString().IndexOf("]",
                StringComparison.Ordinal) - 1));
            var currentItemIndex = (int)item_id_index_map[id];

            if (currentItemIndex <= -1) return;

            checkBox_PWActive.Checked = GSHOP.items[currentItemIndex].activate;
            numericUpDown_PWItemID.Value = GSHOP.items[currentItemIndex].item_id;
            numericUpDown_PWAmount.Value = GSHOP.items[currentItemIndex].item_amount;
            textBox_PWGShopName.Text = PWBytesToString(GSHOP.items[currentItemIndex].name, "Unicode");
            comboBox_PWSurface.Text = PWBytesToString(GSHOP.items[currentItemIndex].surface_path, "GBK");
            textBox_PWDescription.Text = PWBytesToString(GSHOP.items[currentItemIndex].description, "Unicode");

            if (comboBox_PWSaleOption.SelectedIndex > -1)
            {
                numericUpDown_PWPrice.Value = Convert.ToDecimal(GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].price) / 100;
                textBox_PWEndDate.Text = PWTimestampToString(GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].expire_date);
                textBox_PWDuration.Text = PWSecondsToString(GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].duration);
                textBox_PWStartDate.Text = PWTimestampToString(GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].start_date);
                comboBox_PWType.SelectedIndex = GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].control_type + 1;
                textBox_PWDay.Text = GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].day.ToString(CultureInfo.InvariantCulture);
                comboBox_PWStatus.SelectedIndex = (int) GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].status;
                textBox_PWFlags.Text = GSHOP.items[currentItemIndex].sale_options[comboBox_PWSaleOption.SelectedIndex].flags.ToString(CultureInfo.InvariantCulture);
            }

            numericUpDown_PWGiftID.Value = GSHOP.items[currentItemIndex].gift_id;
            numericUpDown_PWGiftAmount.Value = GSHOP.items[currentItemIndex].gift_amount;
            textBox_PWGiftDuration.Text = GSHOP.items[currentItemIndex].gift_duration.ToString(CultureInfo.InvariantCulture);
            numericUpDown_PWLogPrice.Value = Convert.ToDecimal(GSHOP.items[currentItemIndex].log_price) / 100;
        }

        private void PWLoadDBClick(object sender, EventArgs e)
        {
            TabFlag = GShopTab;

            if (PWSelected)
            {
                var openGShop = new OpenFileDialog();
                openGShop.Filter = Resources.GShopDBFilter;

                if (openGShop.ShowDialog() == DialogResult.OK && File.Exists(openGShop.FileName))
                {
                    try
                    {
                        Cursor = Cursors.WaitCursor;
                        listBox_PWCats.Items.Clear();
                        listBox_PWSubCats.Items.Clear();
                        listBox_PWItems.Items.Clear();

                        GSHOP = new Boutique();

                        item_id_index_map = new SortedList();
                        max_item_id = 0;

                        var gshopStream = File.OpenRead(openGShop.FileName);
                        var gshopReader = new BinaryReader(gshopStream);

                        GSHOP.timestamp = gshopReader.ReadInt32();
                        GSHOP.item_count = gshopReader.ReadInt32();
                        GSHOP.items = new Item[GSHOP.item_count];

                        for (var i = 0; i < GSHOP.items.Length; i++)
                        {
                            GSHOP.items[i] = new Item();
                            GSHOP.items[i].activate = gshopReader.ReadBoolean();
                            GSHOP.items[i].shop_id = gshopReader.ReadInt32();

                            //						GSHOP->items[i]->shop_id = i;
                            max_item_id = Math.Max(max_item_id, GSHOP.items[i].shop_id);
                            item_id_index_map.Add(GSHOP.items[i].shop_id, i);

                            GSHOP.items[i].cat_index = gshopReader.ReadInt32();
                            GSHOP.items[i].sub_cat_index = gshopReader.ReadInt32();
                            GSHOP.items[i].surface_path = gshopReader.ReadBytes(128);
                            GSHOP.items[i].item_id = gshopReader.ReadInt32();
                            GSHOP.items[i].item_amount = gshopReader.ReadInt32();

                            GSHOP.items[i].sale_options = new SaleOption[4];

                            for (var n = 0; n < GSHOP.items[i].sale_options.Length; n++)
                            {
                                GSHOP.items[i].sale_options[n] = new SaleOption();
                                GSHOP.items[i].sale_options[n].price = (uint)gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].expire_date = (uint)gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].duration = (uint)gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].start_date = (uint)gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].control_type = gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].day = (uint)gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].status = (uint)gshopReader.ReadInt32();
                                GSHOP.items[i].sale_options[n].flags = (uint)gshopReader.ReadInt32();
                            }

                            GSHOP.items[i].description = gshopReader.ReadBytes(1024);
                            GSHOP.items[i].name = gshopReader.ReadBytes(64);
                            GSHOP.items[i].gift_id = gshopReader.ReadInt32();
                            GSHOP.items[i].gift_amount = gshopReader.ReadInt32();
                            GSHOP.items[i].gift_duration = gshopReader.ReadInt32();
                            GSHOP.items[i].log_price = gshopReader.ReadInt32();
                        }

                        GSHOP.categories = new Category[8];

                        for (var i = 0; i < GSHOP.categories.Length; i++)
                        {
                            GSHOP.categories[i] = new Category();
                            GSHOP.categories[i].name = gshopReader.ReadBytes(128);
                            GSHOP.categories[i].sub_cats_count = gshopReader.ReadInt32();
                            GSHOP.categories[i].sub_cats = new byte[GSHOP.categories[i].sub_cats_count][];

                            for (var n = 0; n < GSHOP.categories[i].sub_cats.Length; n++)
                                GSHOP.categories[i].sub_cats[n] = gshopReader.ReadBytes(128);

                            listBox_PWCats.Items.Add(PWBytesToString(GSHOP.categories[i].name, "Unicode"));
                        }

                        gshopReader.Close();
                        gshopStream.Close();

                        PWBuildContextMenus();
                        textBox_PWTimestamp.Text = PWTimestampToString((uint)GSHOP.timestamp);

                        Cursor = Cursors.Default;
                    }
                    catch (Exception gshopEx)
                    {
                        Cursor = Cursors.Default;
                        MessageBox.Show(Resources.ErrLoadGShop + gshopEx.Message);
                    }
                }
            }
            if (JDSelected) MessageBox.Show(Resources.NotSupported);
        }

        private void PWSaveDBClick(object sender, EventArgs e)
        {
            var save = new SaveFileDialog();
            save.Filter = Resources.GShopDBFilter;

            if (GSHOP == null || save.ShowDialog() != DialogResult.OK) return;

            try
            {
                Cursor = Cursors.WaitCursor;

                var fw = new FileStream(save.FileName, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fw);

                GSHOP.timestamp = (int) PWStringToTimestamp(textBox_PWTimestamp.Text);
                bw.Write(GSHOP.timestamp);
                bw.Write(GSHOP.item_count);

#pragma warning disable 219
                var shopID = 0;
#pragma warning restore 219

                foreach (var t in GSHOP.items.Where(t => t.cat_index > -1 && t.sub_cat_index > -1))
                {
                    bw.Write(t.activate);
                    bw.Write(t.shop_id); //bw->Write(shop_id);
                    bw.Write(t.cat_index);
                    bw.Write(t.sub_cat_index);
                    bw.Write(t.surface_path);
                    bw.Write(t.item_id);
                    bw.Write(t.item_amount);

                    foreach (var u in t.sale_options)
                    {
                        bw.Write(u.price);
                        bw.Write(u.expire_date);
                        bw.Write(u.duration);
                        bw.Write(u.start_date);
                        bw.Write(u.control_type);
                        bw.Write(u.day);
                        bw.Write(u.status);
                        bw.Write(u.flags);
                    }

                    bw.Write(t.description);
                    bw.Write(t.name);
                    bw.Write(t.gift_id);
                    bw.Write(t.gift_amount);
                    bw.Write(t.gift_duration);
                    bw.Write(t.log_price);

                    shopID++;
                }

                foreach (var t in GSHOP.categories)
                {
                    bw.Write(t.name);
                    bw.Write(t.sub_cats.Length);

                    foreach (var u in t.sub_cats)
                        bw.Write(u);
                }

                bw.Close();
                fw.Close();

                Cursor = Cursors.Default;
            }
            catch (Exception gshopEx)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(Resources.ErrSaveGShopDB + gshopEx.Message);
            }
        }

        private void PWExport136Click(object sender, EventArgs e)
        {
            MessageBox.Show(Resources.NotSupported);
            /*
            var save = new SaveFileDialog();
            save.Filter = Resources.GShopFilter;

            if (GSHOP == null || save.ShowDialog() != DialogResult.OK) return;

            try
            {
                Cursor = Cursors.WaitCursor;

                var fw = new FileStream(save.FileName, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fw);

                bw.Write(GSHOP.timestamp);
                bw.Write(GSHOP.item_count);
                var shopID = 0;

                foreach (var t in GSHOP.items.Where(t => t.cat_index > -1 && t.sub_cat_index > -1))
                {
                    // shop id in client server cn be different
                    // so we can use an increment value
                    bw.Write(shopID);
                    bw.Write(t.cat_index);
                    bw.Write(t.sub_cat_index);
                    bw.Write(t.surface_path);
                    bw.Write(t.item_id);
                    bw.Write(t.item_amount);

                    foreach (var t1 in t.sale_options)
                    {
                        bw.Write(t1.price);
                        bw.Write(0); //bw->Write(GSHOP->items[i]->sale_options[n]->expire_date);
                        bw.Write(t1.duration);
                        bw.Write(0); //bw->Write(GSHOP->items[i]->sale_options[n]->start_date);
                        bw.Write(t1.type);
                        bw.Write(t1.day);
                        bw.Write(t1.status);
                        bw.Write(t1.flags);
                    }

                    bw.Write(t.description);
                    bw.Write(t.name);
                    bw.Write(t.gift_id);
                    bw.Write(t.gift_amount);
                    bw.Write(t.gift_duration);
                    bw.Write(t.log_price);

                    shopID++;
                }

                foreach (var t in GSHOP.categories)
                {
                    bw.Write(t.name);
                    bw.Write(t.sub_cats.Length);

                    foreach (var u in t.sub_cats)
                        bw.Write(u);
                }

                bw.Close();
                fw.Close();

                Cursor = Cursors.Default;
            }
            catch (Exception e)
            {
                Cursor = Cursors.Default;
                MessageBox.Show("EXPORT ERROR!\n\n" + e.Message);
            }
            */
        }

        private void PWExport144CClick(object sender, EventArgs e)
        {
            var save = new SaveFileDialog();
            save.Filter = Resources.GShopFilter;

            if (GSHOP == null || save.ShowDialog() != DialogResult.OK) return;

            try
            {
                Cursor = Cursors.WaitCursor;

                var fw = new FileStream(save.FileName, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fw);

                GSHOP.timestamp = (int)PWStringToTimestamp(textBox_PWTimestamp.Text);
                bw.Write(GSHOP.timestamp);
                bw.Write(GSHOP.item_count);
#pragma warning disable 219
                var shopID = 0;
#pragma warning restore 219

                foreach (var t in GSHOP.items.Where(t => t.cat_index > -1 && t.sub_cat_index > -1))
                {
                    bw.Write(t.shop_id); //bw->Write(shop_id);
                    bw.Write(t.cat_index);
                    bw.Write(t.sub_cat_index);
                    bw.Write(t.surface_path);
                    bw.Write(t.item_id);
                    bw.Write(t.item_amount);

                    foreach (var u in t.sale_options)
                    {
                        // only write values to client when control_type = "client"
                        if (u.control_type == -1)
                        {
                            bw.Write(u.price);
                            bw.Write(u.expire_date);
                            bw.Write(u.duration);
                            bw.Write(u.start_date);
                        }
                        else
                        {
                            bw.Write((uint)0);
                            bw.Write((uint)0);
                            bw.Write((uint)0);
                            bw.Write((uint)0);
                        }
                        // bw.Write((uint)0); // never write end_date to client (seems to be controled by server)
                        // bw.Write(GSHOP.items[i].sale_options[n].duration); // always write duration to client
                        // bw.Write((uint)0); // never write start_date to client (seems to be controled by server)
                        bw.Write(u.control_type);
                        bw.Write(u.day);
                        bw.Write(u.status);
                        bw.Write(u.flags);
                    }

                    bw.Write(t.description);
                    bw.Write(t.name);
                    bw.Write(t.gift_id);
                    bw.Write(t.gift_amount);
                    bw.Write(t.gift_duration);
                    bw.Write(t.log_price);

                    shopID++;
                }

                foreach (var t in GSHOP.categories)
                {
                    bw.Write(t.name);
                    bw.Write(t.sub_cats.Length);

                    foreach (var u in t.sub_cats)
                        bw.Write(u);
                }

                bw.Close();
                fw.Close();

                Cursor = Cursors.Default;
            }
            catch (Exception gshopExE144)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(Resources.ErrExportGShop + gshopExE144.Message);
            }
        }

        private void PWExport144SClick(object sender, EventArgs e)
        {
            var save = new SaveFileDialog();
            save.Filter = Resources.GShopSevFilter;

            if (GSHOP == null || save.ShowDialog() != DialogResult.OK) return;

            try
            {
                Cursor = Cursors.WaitCursor;

                var fw = new FileStream(save.FileName, FileMode.Create, FileAccess.Write);
                var bw = new BinaryWriter(fw);

                GSHOP.timestamp = (int)PWStringToTimestamp(textBox_PWTimestamp.Text);
                bw.Write(GSHOP.timestamp);

                var activeItemCount = GSHOP.items.Count(t => t.activate && t.cat_index > -1 && t.sub_cat_index > -1);

                bw.Write(activeItemCount); //bw.Write(GSHOP.item_count);

#pragma warning disable 219
                var shopID = 0;
#pragma warning restore 219


                foreach (var t in GSHOP.items.Where(t => t.activate && t.cat_index > -1 && t.sub_cat_index > -1))
                {
                    bw.Write(t.shop_id); //bw->Write(shop_id);
                    bw.Write(t.cat_index);
                    bw.Write(t.sub_cat_index);
                    bw.Write(t.item_id);
                    bw.Write(t.item_amount);

                    foreach (var u in t.sale_options)
                    {
                        bw.Write(u.price);
                        bw.Write(u.expire_date);
                        bw.Write(u.duration);
                        bw.Write(u.start_date);
                        bw.Write(u.control_type);
                        bw.Write(u.day);
                        bw.Write(u.status);
                        bw.Write(u.flags);
                    }

                    bw.Write(t.gift_id);
                    bw.Write(t.gift_amount);
                    bw.Write(t.gift_duration);
                    bw.Write(t.log_price);

                    shopID++;
                }

                bw.Close();
                fw.Close();

                Cursor = Cursors.Default;
            }
            catch (Exception gshopExS144)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(Resources.ErrExportGShop + gshopExS144.Message);
            }
        }

        private void PWImport136Click(object sender, EventArgs e)
        {
            var load = new OpenFileDialog();
            load.Filter = Resources.GShopFilter;

            if (load.ShowDialog() != DialogResult.OK || !File.Exists(load.FileName)) return;

            try
            {
                Cursor = Cursors.WaitCursor;
                listBox_PWCats.Items.Clear();
                listBox_PWSubCats.Items.Clear();
                listBox_PWItems.Items.Clear();

                GSHOP = new Boutique();
                item_id_index_map = new SortedList();
                max_item_id = 0;

                var fr = File.OpenRead(load.FileName);
                var br = new BinaryReader(fr);

                GSHOP.timestamp = br.ReadInt32();
                GSHOP.item_count = br.ReadInt32();
                GSHOP.items = new Item[GSHOP.item_count];

                for (var i = 0; i < GSHOP.items.Length; i++)
                {
                    GSHOP.items[i] = new Item();
                    GSHOP.items[i].activate = true;
                    GSHOP.items[i].shop_id = br.ReadInt32();
                    //						GSHOP.items[i].shop_id = i;
                    max_item_id = Math.Max(max_item_id, GSHOP.items[i].shop_id);
                    item_id_index_map.Add(GSHOP.items[i].shop_id, i);
                    GSHOP.items[i].cat_index = br.ReadInt32();
                    GSHOP.items[i].sub_cat_index = br.ReadInt32();
                    GSHOP.items[i].surface_path = br.ReadBytes(128);
                    GSHOP.items[i].item_id = br.ReadInt32();
                    GSHOP.items[i].item_amount = br.ReadInt32();

                    GSHOP.items[i].sale_options = new SaleOption[4];

                    for (var n = 0; n < GSHOP.items[i].sale_options.Length; n++)
                    {
                        GSHOP.items[i].sale_options[n] = new SaleOption();
                        // read price
                        GSHOP.items[i].sale_options[n].price = (uint)br.ReadInt32();
                        // ignore unknown value
                        br.ReadInt32();
                        GSHOP.items[i].sale_options[n].expire_date = 0;
                        // read duration
                        GSHOP.items[i].sale_options[n].duration = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].start_date = 0;
                        GSHOP.items[i].sale_options[n].control_type = -1;
                        GSHOP.items[i].sale_options[n].day = 0;
                        GSHOP.items[i].sale_options[n].status = 0;
                        GSHOP.items[i].sale_options[n].flags = 0;
                    }

                    // read status and apply to first sale option
                    GSHOP.items[i].sale_options[0].status = (uint)br.ReadInt32();

                    GSHOP.items[i].description = br.ReadBytes(1024);
                    GSHOP.items[i].name = br.ReadBytes(64);
                    GSHOP.items[i].gift_id = 0;
                    GSHOP.items[i].gift_amount = 0;
                    GSHOP.items[i].gift_duration = 0;
                    GSHOP.items[i].log_price = 0;
                }

                GSHOP.categories = new Category[8];

                for (var i = 0; i < GSHOP.categories.Length; i++)
                {
                    GSHOP.categories[i] = new Category();
                    GSHOP.categories[i].name = br.ReadBytes(128);
                    GSHOP.categories[i].sub_cats_count = br.ReadInt32();
                    GSHOP.categories[i].sub_cats = new byte[GSHOP.categories[i].sub_cats_count][];

                    for (var n = 0; n < GSHOP.categories[i].sub_cats.Length; n++)
                        GSHOP.categories[i].sub_cats[n] = br.ReadBytes(128);

                    listBox_PWCats.Items.Add(PWBytesToString(GSHOP.categories[i].name, "Unicode"));
                }

                br.Close();
                fr.Close();

                PWBuildContextMenus();
                textBox_PWTimestamp.Text = PWTimestampToString((uint)GSHOP.timestamp);

                Cursor = Cursors.Default;
            }
            catch (Exception gshopExImp136)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(Resources.ErrImpGShop + gshopExImp136.Message);
            }
        }

        private void PWImport144CClick(object sender, EventArgs e)
        {
            var load = new OpenFileDialog();
            load.Filter = Resources.GShopFilter;

            if (load.ShowDialog() != DialogResult.OK || !File.Exists(load.FileName)) return;

            try
            {
                Cursor = Cursors.WaitCursor;
                listBox_PWCats.Items.Clear();
                listBox_PWSubCats.Items.Clear();
                listBox_PWItems.Items.Clear();

                GSHOP = new Boutique();
                item_id_index_map = new SortedList();
                max_item_id = 0;

                var fr = File.OpenRead(load.FileName);
                var br = new BinaryReader(fr);

                GSHOP.timestamp = br.ReadInt32();
                GSHOP.item_count = br.ReadInt32();
                GSHOP.items = new Item[GSHOP.item_count];

                for (var i = 0; i < GSHOP.items.Length; i++)
                {
                    GSHOP.items[i] = new Item();
                    GSHOP.items[i].activate = true;
                    GSHOP.items[i].shop_id = br.ReadInt32();
                    //						GSHOP.items[i].shop_id = i;
                    max_item_id = Math.Max(max_item_id, GSHOP.items[i].shop_id);
                    item_id_index_map.Add(GSHOP.items[i].shop_id, i);
                    GSHOP.items[i].cat_index = br.ReadInt32();
                    GSHOP.items[i].sub_cat_index = br.ReadInt32();
                    GSHOP.items[i].surface_path = br.ReadBytes(128);
                    GSHOP.items[i].item_id = br.ReadInt32();
                    GSHOP.items[i].item_amount = br.ReadInt32();

                    GSHOP.items[i].sale_options = new SaleOption[4];

                    for (var n = 0; n < GSHOP.items[i].sale_options.Length; n++)
                    {
                        GSHOP.items[i].sale_options[n] = new SaleOption();
                        GSHOP.items[i].sale_options[n].price = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].expire_date = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].duration = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].start_date = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].control_type = br.ReadInt32();
                        GSHOP.items[i].sale_options[n].day = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].status = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].flags = (uint)br.ReadInt32();
                    }

                    GSHOP.items[i].description = br.ReadBytes(1024);
                    GSHOP.items[i].name = br.ReadBytes(64);
                    GSHOP.items[i].gift_id = br.ReadInt32();
                    GSHOP.items[i].gift_amount = br.ReadInt32();
                    GSHOP.items[i].gift_duration = br.ReadInt32();
                    GSHOP.items[i].log_price = br.ReadInt32();
                }

                GSHOP.categories = new Category[8];
                for (var i = 0; i < GSHOP.categories.Length; i++)
                {
                    GSHOP.categories[i] = new Category();
                    GSHOP.categories[i].name = br.ReadBytes(128);
                    GSHOP.categories[i].sub_cats_count = br.ReadInt32();
                    GSHOP.categories[i].sub_cats = new byte[GSHOP.categories[i].sub_cats_count][];

                    for (var n = 0; n < GSHOP.categories[i].sub_cats.Length; n++)
                        GSHOP.categories[i].sub_cats[n] = br.ReadBytes(128);

                    listBox_PWCats.Items.Add(PWBytesToString(GSHOP.categories[i].name, "Unicode"));
                }

                br.Close();
                fr.Close();

                PWBuildContextMenus();
                textBox_PWTimestamp.Text = PWTimestampToString((uint)GSHOP.timestamp);

                Cursor = Cursors.Default;
            }
            catch (Exception gshopExImp144C)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(Resources.ErrImpGShop + gshopExImp144C.Message);
            }
        }

        private void PWImport144SClick(object sender, EventArgs e)
        {
            var load = new OpenFileDialog();
            load.Filter = Resources.GShopFilter;

            if (load.ShowDialog() != DialogResult.OK || !File.Exists(load.FileName)) return;

            try
            {
                Cursor = Cursors.WaitCursor;
                listBox_PWCats.Items.Clear();
                listBox_PWSubCats.Items.Clear();
                listBox_PWItems.Items.Clear();

                GSHOP = new Boutique();
                GSHOP.categories = new Category[8];

                for (var i = 0; i < GSHOP.categories.Length; i++)
                {
                    GSHOP.categories[i] = new Category();
                    GSHOP.categories[i].name = PWStringToBytes("NULL", "Unicode", 128);
                    GSHOP.categories[i].sub_cats_count = 0;
                }

                item_id_index_map = new SortedList();
                max_item_id = 0;

                var fr = File.OpenRead(load.FileName);
                var br = new BinaryReader(fr);

                GSHOP.timestamp = br.ReadInt32();
                GSHOP.item_count = br.ReadInt32();
                GSHOP.items = new Item[GSHOP.item_count];

                for (var i = 0; i < GSHOP.items.Length; i++)
                {
                    GSHOP.items[i] = new Item();
                    GSHOP.items[i].activate = true;
                    GSHOP.items[i].shop_id = br.ReadInt32();
                    //						GSHOP->items[i]->shop_id = i;
                    max_item_id = Math.Max(max_item_id, GSHOP.items[i].shop_id);
                    item_id_index_map.Add(GSHOP.items[i].shop_id, i);
                    GSHOP.items[i].cat_index = br.ReadInt32();
                    GSHOP.items[i].sub_cat_index = br.ReadInt32();
                    // update counter for subcategories
                    GSHOP.categories[GSHOP.items[i].cat_index].sub_cats_count =
                        Math.Max(GSHOP.categories[GSHOP.items[i].cat_index].sub_cats_count, GSHOP.items[i].sub_cat_index + 1);
                    GSHOP.items[i].surface_path = new byte[128];
                    GSHOP.items[i].item_id = br.ReadInt32();
                    GSHOP.items[i].item_amount = br.ReadInt32();

                    GSHOP.items[i].sale_options = new SaleOption[4];

                    for (var n = 0; n < GSHOP.items[i].sale_options.Length; n++)
                    {
                        GSHOP.items[i].sale_options[n] = new SaleOption();
                        GSHOP.items[i].sale_options[n].price = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].expire_date = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].duration = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].start_date = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].control_type = br.ReadInt32();
                        GSHOP.items[i].sale_options[n].day = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].status = (uint)br.ReadInt32();
                        GSHOP.items[i].sale_options[n].flags = (uint)br.ReadInt32();
                    }

                    GSHOP.items[i].description = new byte[1024];
                    GSHOP.items[i].name = new byte[64];
                    GSHOP.items[i].gift_id = br.ReadInt32();
                    GSHOP.items[i].gift_amount = br.ReadInt32();
                    GSHOP.items[i].gift_duration = br.ReadInt32();
                    GSHOP.items[i].log_price = br.ReadInt32();
                }

                foreach (var t in GSHOP.categories)
                {
                    t.sub_cats = new byte[t.sub_cats_count][];

                    for (var n = 0; n < t.sub_cats.Length; n++)
                        t.sub_cats[n] = PWStringToBytes("NULL", "Unicode", 128);

                    listBox_PWCats.Items.Add(PWBytesToString(t.name, "Unicode"));
                }

                br.Close();
                fr.Close();

                PWBuildContextMenus();
                textBox_PWTimestamp.Text = PWTimestampToString((uint)GSHOP.timestamp);

                Cursor = Cursors.Default;
            }
            catch (Exception gshopExImp144S)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(Resources.ErrImpGShop + gshopExImp144S.Message);
            }
        }
        
        private void PWSetAllDefaultPrices1000Click(object sender, EventArgs e)
        {
            if (GSHOP == null) return;

            Cursor = Cursors.WaitCursor;

            foreach (var t in GSHOP.items)
                t.sale_options[0].price = 1000;

            PWChangeItem(null, null);

            Cursor = Cursors.Default;
        }

        private void PWSetAllControlTypesClientClick(object sender, EventArgs e)
        {
            if (GSHOP == null) return;

            Cursor = Cursors.WaitCursor;

            foreach (var u in GSHOP.items.SelectMany(t => t.sale_options))
                u.control_type = -1;

            PWChangeItem(null, null);

            Cursor = Cursors.Default;
        }

        private void PWSetAllControlTypeServerClick(object sender, EventArgs e)
        {
            if (GSHOP == null) return;

            Cursor = Cursors.WaitCursor;

            foreach (var u in GSHOP.items.SelectMany(t => t.sale_options))
                u.control_type = 0;

            PWChangeItem(null, null);

            Cursor = Cursors.Default;
        }

        private void PWMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;

            Cursor = Cursors.SizeNS;
            movingIndex = ((ListBox)sender).SelectedIndex;
        }

        private void PWMouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left || ((ListBox)sender).Items.Count <= 1 ||
                movingIndex == ((ListBox)sender).SelectedIndex) return;

            // Removing Event Handlers
            listBox_PWCats.SelectedIndexChanged -= PWCatsIndexChanged;

            if (Math.Abs(movingIndex - ((ListBox)sender).SelectedIndex) == 1)
            {
                // Swap categories
                var movingCat = GSHOP.categories[movingIndex];
                GSHOP.categories[movingIndex] = GSHOP.categories[((ListBox)sender).SelectedIndex];
                GSHOP.categories[((ListBox)sender).SelectedIndex] = movingCat;

                // Swap listbox items
                var movingListBoxItem = ((ListBox)sender).Items[movingIndex];
                ((ListBox)sender).Items[movingIndex] = ((ListBox)sender).Items[((ListBox)sender).SelectedIndex];
                ((ListBox)sender).Items[((ListBox)sender).SelectedIndex] = movingListBoxItem;

                // Change all Items: Cat Index from movingIndex to ((ListBox^)sender)->SelectedIndex
                foreach (var t in GSHOP.items)
                {
                    if (t.cat_index == movingIndex)
                        t.cat_index = ((ListBox)sender).SelectedIndex;

                    else if (t.cat_index == ((ListBox)sender).SelectedIndex)
                        t.cat_index = movingIndex;
                }

                PWBuildContextMenus();

                movingIndex = ((ListBox)sender).SelectedIndex;
            }
            // Adding Event Handlers
            listBox_PWCats.SelectedIndexChanged += PWCatsIndexChanged;
        }

        private void PWMouseUp(object sender, MouseEventArgs e)
        {
            Cursor = Cursors.Default;
        }

        private void PWCatTextChanged(object sender, EventArgs e)
        {
            if (listBox_PWCats.SelectedIndex <= -1) return;

            GSHOP.categories[listBox_PWCats.SelectedIndex].name = PWStringToBytes(textBox_PWCat.Text, "Unicode", 128);
            listBox_PWCats.Items[listBox_PWCats.SelectedIndex] = textBox_PWCat.Text;

            PWBuildContextMenus();
        }

        private void PWSubCatsMouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left || ((ListBox)sender).Items.Count <= 1 ||
                movingIndex == ((ListBox)sender).SelectedIndex) return;

            // Removing Event Handlers
            listBox_PWSubCats.SelectedIndexChanged -= PWSubCatsIndexChanged;

            if (Math.Abs(movingIndex - ((ListBox)sender).SelectedIndex) == 1)
            {
                // Swap categories
                var movingSubCat = GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats[movingIndex];
                GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats[movingIndex] =
                    GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats[((ListBox)sender).SelectedIndex];
                GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats[((ListBox)sender).SelectedIndex] = movingSubCat;

                // Swap listbox items
                var movingListBoxItem = ((ListBox)sender).Items[movingIndex];
                ((ListBox)sender).Items[movingIndex] = ((ListBox)sender).Items[((ListBox)sender).SelectedIndex];
                ((ListBox)sender).Items[((ListBox)sender).SelectedIndex] = movingListBoxItem;

                // Change all Items: SubCat Index from movingIndex to ((ListBox^)sender)->SelectedIndex
                foreach (var t in GSHOP.items.Where(t => t.cat_index == listBox_PWCats.SelectedIndex))
                {
                    if (t.sub_cat_index == movingIndex)
                        t.sub_cat_index = ((ListBox)sender).SelectedIndex;
                    else if (t.sub_cat_index == ((ListBox)sender).SelectedIndex)
                        t.sub_cat_index = movingIndex;
                }

                PWBuildContextMenus();

                movingIndex = ((ListBox)sender).SelectedIndex;
            }
            // Adding Event Handlers
            listBox_PWSubCats.SelectedIndexChanged += PWSubCatsIndexChanged;
        }

        private void PWSubCatTextChanged(object sender, EventArgs e)
        {
            if (listBox_PWCats.SelectedIndex <= -1 || listBox_PWSubCats.SelectedIndex <= -1) return;

            GSHOP.categories[listBox_PWCats.SelectedIndex].sub_cats[listBox_PWSubCats.SelectedIndex] =
                PWStringToBytes(textBox_PWSubCat.Text, "Unicode", 128);
            listBox_PWSubCats.Items[listBox_PWSubCats.SelectedIndex] = textBox_PWSubCat.Text;

            PWBuildContextMenus();
        }

        private void PWItemsMouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left || ((ListBox)sender).Items.Count <= 1 ||
                movingIndex == ((ListBox)sender).SelectedIndex) return;

            // Removing Event Handlers
            listBox_PWItems.SelectedIndexChanged -= PWChangeItem;

            if (Math.Abs(movingIndex - ((ListBox)sender).SelectedIndex) == 1)
            {
                var sourceID = Convert.ToInt32(listBox_PWItems.Items[movingIndex].ToString().
                    Substring(1, listBox_PWItems.Items[movingIndex].ToString().IndexOf("]", StringComparison.Ordinal) - 1));
                var targetID = Convert.ToInt32(listBox_PWItems.Items[listBox_PWItems.SelectedIndex].ToString().
                    Substring(1, listBox_PWItems.Items[listBox_PWItems.SelectedIndex].ToString().IndexOf("]", StringComparison.Ordinal) - 1));

                // Swap gshop items and update id_index_map
                var movingItem = GSHOP.items[(int)item_id_index_map[sourceID]];
                GSHOP.items[(int)item_id_index_map[sourceID]] = GSHOP.items[(int)item_id_index_map[targetID]];
                GSHOP.items[(int)item_id_index_map[targetID]] = movingItem;

                // Swap id_index_map
                var movingMap = (int)item_id_index_map[sourceID];
                item_id_index_map[sourceID] = item_id_index_map[targetID];
                item_id_index_map[targetID] = movingMap;

                // Swap listbox items
                var movingListBoxItem = ((ListBox)sender).Items[movingIndex];
                ((ListBox)sender).Items[movingIndex] = ((ListBox)sender).Items[((ListBox)sender).SelectedIndex];
                ((ListBox)sender).Items[((ListBox)sender).SelectedIndex] = movingListBoxItem;

                movingIndex = ((ListBox)sender).SelectedIndex;
            }
            // Adding Event Handlers
            listBox_PWItems.SelectedIndexChanged += PWChangeItem;
        }

        private void PWGShopSearchKeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
                PWButtonGShopSearchClick(null, null);
        }

        private void PWButtonGShopSearchClick(object sender, EventArgs e)
        {
            if (GSHOP == null) return;

            // Get the index of current selected item
            var currentItemIndex = 0;
            if (listBox_PWItems.SelectedIndex > -1)
            {
                var id = Convert.ToInt32(listBox_PWItems.SelectedItem.ToString().
                                             Substring(1, listBox_PWItems.SelectedItem.ToString().IndexOf("]", StringComparison.Ordinal) - 1));
                currentItemIndex = (int)item_id_index_map[id] + 1;
            }

            for (var i = currentItemIndex; i < GSHOP.items.Length; i++)
            {
                if (GSHOP.items[i].cat_index <= -1 || GSHOP.items[i].sub_cat_index <= -1) continue;

                if (textBox_search.Text != GSHOP.items[i].item_id.ToString(CultureInfo.InvariantCulture) &&
                    !PWBytesToString(GSHOP.items[i].name, "Unicode").Contains(textBox_search.Text)) continue;

                listBox_PWCats.SelectedIndex = GSHOP.items[i].cat_index;
                listBox_PWSubCats.SelectedIndex = GSHOP.items[i].sub_cat_index;
                listBox_PWItems.SelectedIndex = listBox_PWItems.Items.
                    IndexOf("[" + GSHOP.items[i].shop_id.ToString(CultureInfo.InvariantCulture) + "] " +
                            PWBytesToString(GSHOP.items[i].name, "Unicode"));
                return;
            }

            MessageBox.Show(Resources.GShopSearchNoFind);
        }

        private void PWButtonAutoDetectClick(object sender, EventArgs e)
        {
            Cursor = Cursors.AppStarting;

            if (comboBox_PWdbSource.SelectedIndex < 1)
            {
                var description = (string)itemDescriptions[numericUpDown_PWItemID.Value.ToString(CultureInfo.InvariantCulture)];
                if (description != null)
                {
                    description = description.Replace("\\r", " \\r");
                    textBox_PWDescription.Text = description;
                }

                PWEditItem(textBox_PWDescription, null);
            }
            else
            {
                try
                {
                    int length;

                    var request = (HttpWebRequest)WebRequest.Create("http://www." +
                        comboBox_PWdbSource.SelectedItem + "/items/" +
                        numericUpDown_PWItemID.Value.ToString(CultureInfo.InvariantCulture));
                    request.Proxy = null;
                    var response = (HttpWebResponse)request.GetResponse();
                    // ReSharper disable AssignNullToNotNullAttribute
                    var wr = new StreamReader(response.GetResponseStream());
                    // ReSharper restore AssignNullToNotNullAttribute
                    var content = wr.ReadToEnd();
                    wr.Close();

                    // Find Item Name
                    var index = content.IndexOf("<th class=\"itemHeader\"", StringComparison.Ordinal) + 35;
                    if (index > 34)
                    {
                        length = content.IndexOf("<a href", index, StringComparison.Ordinal) - index;
                        var name = content.Substring(index, length);

                        // Remove span + color
                        if (name.Contains("<"))
                        {
                            name = name.Substring(name.IndexOf(">", StringComparison.Ordinal) + 1);
                            name = name.Substring(0, name.IndexOf("</", StringComparison.Ordinal));
                        }

                        name = name.Replace("&#9734;", "★");
                        textBox_PWGShopName.Text = name;
                        PWEditItem(textBox_PWGShopName, null);
                    }

                    // Find if Item Contains Shop Info
                    index = content.IndexOf("<a href=\"shopitem/", index, StringComparison.Ordinal) + 18;

                    if (index > 18)
                    {
                        length = content.IndexOf("\">", index, StringComparison.Ordinal) - index;
                        var shopID = content.Substring(index, length);

                        // Load Shop Description
                        request = (HttpWebRequest)WebRequest.Create("http://www." + comboBox_PWdbSource.SelectedItem + "/shopitem/" + shopID);
                        request.Proxy = null;
                        response = (HttpWebResponse)request.GetResponse();
                        // ReSharper disable AssignNullToNotNullAttribute
                        wr = new StreamReader(response.GetResponseStream());
                        // ReSharper restore AssignNullToNotNullAttribute
                        content = wr.ReadToEnd();
                        wr.Close();

                        index = content.IndexOf("<h3>Description</h3><p>", StringComparison.Ordinal) + 23;
                        if (index > 22)
                        {
                            length = content.IndexOf("</p>", index, StringComparison.Ordinal) - index;
                            string description = content.Substring(index, length);

                            description = description.Replace("<span style='color:", "");
                            description = description.Replace("#", "^");
                            description = description.Replace(";", "");
                            description = description.Replace("'>", "");
                            description = description.Replace("<br />", "\\r");
                            description = description.Replace("<br/>", "\\r");
                            description = description.Replace("<br>", "\\r");
                            description = description.Replace("</span>", "");
                            description = description.Replace("\\r", " \\r");

                            textBox_PWDescription.Text = description;
                        }
                    }

                    PWEditItem(textBox_PWDescription, null);
                }
                catch
                {
                    MessageBox.Show(Resources.ConnectionFail);
                }
            }

            Cursor = Cursors.Default;
        }

        private void PWEditItem(object sender, EventArgs e)
        {
            if (listBox_PWItems.SelectedIndex <= -1) return;

            var id = Convert.ToInt32(listBox_PWItems.SelectedItem.ToString().
                Substring(1, listBox_PWItems.SelectedItem.ToString().IndexOf("]", StringComparison.Ordinal) - 1));
            var currentItemIndex = (int)item_id_index_map[id];
            var currentSaleIndex = comboBox_PWSaleOption.SelectedIndex;

            if (sender == checkBox_PWActive)
                GSHOP.items[currentItemIndex].activate = checkBox_PWActive.Checked;

            if (sender == numericUpDown_PWItemID)
                GSHOP.items[currentItemIndex].item_id = Convert.ToInt32(numericUpDown_PWItemID.Value);

            if (sender == numericUpDown_PWAmount)
                GSHOP.items[currentItemIndex].item_amount = Convert.ToInt32(numericUpDown_PWAmount.Value);

            if (sender == textBox_PWGShopName)
            {
                GSHOP.items[currentItemIndex].name = PWStringToBytes(textBox_PWGShopName.Text, "Unicode", 64);
                listBox_PWItems.Items[listBox_PWItems.SelectedIndex] =
                    "[" + GSHOP.items[currentItemIndex].shop_id + "] " + textBox_PWGShopName.Text;
            }

            if (sender == textBox_PWDescription)
                GSHOP.items[currentItemIndex].description = PWStringToBytes(textBox_PWDescription.Text, "Unicode", 1024);

            if (sender == comboBox_PWSurface)
                GSHOP.items[currentItemIndex].surface_path = PWStringToBytes(comboBox_PWSurface.Text, "GBK", 128);

            if (sender == numericUpDown_PWPrice)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].price =
                    (uint)Convert.ToInt32(100 * numericUpDown_PWPrice.Value);

            if (sender == comboBox_PWType)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].control_type =
                    Convert.ToInt32(comboBox_PWType.SelectedIndex - 1);

            if (sender == textBox_PWStartDate)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].start_date =
                    PWStringToTimestamp(textBox_PWStartDate.Text);

            if (sender == textBox_PWEndDate)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].expire_date =
                    PWStringToTimestamp(textBox_PWEndDate.Text);

            if (sender == textBox_PWDuration)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].duration =
                    PWStringToSeconds(textBox_PWDuration.Text);

            if (sender == textBox_PWDay)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].day = Convert.ToUInt32(textBox_PWDay.Text);

            if (sender == comboBox_PWStatus)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].status =
                    (uint)comboBox_PWStatus.SelectedIndex;
            if (sender == textBox_PWFlags)
                GSHOP.items[currentItemIndex].sale_options[currentSaleIndex].flags = Convert.ToUInt32(textBox_PWFlags.Text);

            if (sender == numericUpDown_PWGiftID)
                GSHOP.items[currentItemIndex].gift_id = Convert.ToInt32(numericUpDown_PWGiftID.Value);

            if (sender == numericUpDown_PWGiftAmount)
                GSHOP.items[currentItemIndex].gift_amount = Convert.ToInt32(numericUpDown_PWGiftAmount.Value);

            if (sender == textBox_PWGiftDuration)
                GSHOP.items[currentItemIndex].gift_duration = (int)Convert.ToUInt32(textBox_PWGiftDuration.Text);
            // StringToSeconds(textBox_gift_duration.Text);

            if (sender == numericUpDown_PWLogPrice)
                GSHOP.items[currentItemIndex].log_price = Convert.ToInt32(100 * numericUpDown_PWLogPrice.Value);
        }

        private void PWComboBoxSurfaceTextChanged(object sender, EventArgs e)
        {
            var surface = Application.StartupPath + "\\" + comboBox_PWSurface.Text.Replace(".dds", ".jpg");
            var surfacePath = surface.Substring(0, surface.LastIndexOf("\\", StringComparison.Ordinal));
            var file = surface.Substring(surface.LastIndexOf("\\", StringComparison.Ordinal) + 1);

            if (surfacePath.IndexOfAny(Path.GetInvalidPathChars()) < 0 &&
                file.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 && File.Exists(surface))
                pictureBox_PWSurface.Image = Image.FromFile(surface);
            else
                pictureBox_PWSurface.Image = new Bitmap(128, 128);

            GC.Collect();
        }

        private void PWAddClick(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWCats.SelectedIndex <= -1 || listBox_PWSubCats.SelectedIndex <= -1) return;

            GSHOP.item_count++;
            Array.Resize(ref GSHOP.items, GSHOP.items.Length + 1);

            GSHOP.items[GSHOP.items.Length - 1] = new Item();
            GSHOP.items[GSHOP.items.Length - 1].activate = true;
            GSHOP.items[GSHOP.items.Length - 1].shop_id = max_item_id + 1;
            GSHOP.items[GSHOP.items.Length - 1].cat_index = listBox_PWCats.SelectedIndex;
            GSHOP.items[GSHOP.items.Length - 1].sub_cat_index = listBox_PWSubCats.SelectedIndex;
            GSHOP.items[GSHOP.items.Length - 1].surface_path = PWStringToBytes("", "GBK", 128);
            GSHOP.items[GSHOP.items.Length - 1].item_id = 1;
            GSHOP.items[GSHOP.items.Length - 1].item_amount = 1;

            GSHOP.items[GSHOP.items.Length - 1].sale_options = new SaleOption[4];

            for (var n = 0; n < GSHOP.items[GSHOP.items.Length - 1].sale_options.Length; n++)
            {
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n] = new SaleOption();
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].price = 0;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].expire_date = 0;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].duration = 0;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].start_date = 0;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].control_type = -1;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].day = 0;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].status = 0;
                GSHOP.items[GSHOP.items.Length - 1].sale_options[n].flags = 0;
            }

            GSHOP.items[GSHOP.items.Length - 1].description = PWStringToBytes("", "Unicode", 1024);
            GSHOP.items[GSHOP.items.Length - 1].name = PWStringToBytes("New", "Unicode", 64);
            GSHOP.items[GSHOP.items.Length - 1].gift_id = 0;
            GSHOP.items[GSHOP.items.Length - 1].gift_amount = 0;
            GSHOP.items[GSHOP.items.Length - 1].gift_duration = 0;
            GSHOP.items[GSHOP.items.Length - 1].log_price = 0;

            item_id_index_map.Add(GSHOP.items[GSHOP.items.Length - 1].shop_id, GSHOP.items.Length - 1);

            listBox_PWItems.Items.Add("[" + GSHOP.items[GSHOP.items.Length - 1].shop_id + "] New");
            listBox_PWItems.SelectedIndex = listBox_PWItems.Items.Count - 1;

            max_item_id++;
        }

        private void PWDeleteClick(object sender, EventArgs e)
        {
            if (GSHOP == null || listBox_PWItems.SelectedIndex <= -1) return;

            var id = Convert.ToInt32(listBox_PWItems.SelectedItem.ToString().
                Substring(1, listBox_PWItems.SelectedItem.ToString().IndexOf("]", StringComparison.Ordinal) - 1));
            var currentItemIndex = (int)item_id_index_map[id];

            // mark this item as not to be saved
            GSHOP.item_count--;
            GSHOP.items[currentItemIndex].cat_index = -1;
            GSHOP.items[currentItemIndex].sub_cat_index = -1;

            item_id_index_map.Remove(GSHOP.items[currentItemIndex].shop_id);
            listBox_PWItems.Items.RemoveAt(listBox_PWItems.SelectedIndex);
        }
        
    }
}
